package org.dromara.mqtt.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.mqtt.config.MqttProperties;
import org.dromara.mqtt.domain.bo.DeviceControlBoPara;
import org.dromara.mqtt.tools.MqttMessageBuilder;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.stereotype.Service;
import org.dromara.mqtt.domain.DeviceControl;
import org.dromara.mqtt.domain.bo.DeviceControlBo;
import org.dromara.mqtt.domain.vo.DeviceControlVo;
import org.dromara.mqtt.mapper.DeviceControlMapper;
import org.dromara.mqtt.service.IDeviceControlService;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * IoT设备控制Service业务层处理
 *
 * @author Miles Meng
 * @date 2025-09-01
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DeviceControlServiceImpl implements IDeviceControlService {

    private final DeviceControlMapper deviceControlMapper;
    private final MqttClientService mqttClientService;
    private final MqttProperties mqttProperties;

    /**
     * 查询设备控制
     */
    @Override
    public DeviceControlVo queryById(Long id) {
        return deviceControlMapper.selectVoById(id);
    }

    /**
     * 查询设备控制列表
     */
    @Override
    public TableDataInfo<DeviceControlVo> queryPageList(DeviceControlBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DeviceControl> lqw = buildQueryWrapper(bo);
        Page<DeviceControlVo> result = deviceControlMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询设备控制列表
     */
    @Override
    public List<DeviceControlVo> queryList(DeviceControlBo bo) {
        LambdaQueryWrapper<DeviceControl> lqw = buildQueryWrapper(bo);
        return deviceControlMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceControl> buildQueryWrapper(DeviceControlBo bo) {
        LambdaQueryWrapper<DeviceControl> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getDeviceId()), DeviceControl::getDeviceId, bo.getDeviceId());
        lqw.eq(StringUtils.isNotBlank(bo.getMethod()), DeviceControl::getMethod, bo.getMethod());
        lqw.eq(bo.getCode() != null, DeviceControl::getCode, bo.getCode());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), DeviceControl::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getMessageType()), DeviceControl::getMessageType, bo.getMessageType());
        return lqw;
    }

    /**
     * 新增设备控制
     */
    @Override
    public Boolean insertByBo(DeviceControlBo bo) {
        DeviceControl add = MapstructUtils.convert(bo, DeviceControl.class);
        validEntityBeforeSave(add);
        boolean flag = deviceControlMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改设备控制
     */
    @Override
    public Boolean updateByBo(DeviceControlBo bo) {
        DeviceControl update = MapstructUtils.convert(bo, DeviceControl.class);
        validEntityBeforeSave(update);
        return deviceControlMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceControl entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除设备控制信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return deviceControlMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 控制设备电源开关
     */
    @Override
    public Boolean setPowerSwitch(DeviceControlBoPara bo) {
        // 构造控制指令并发送到MQTT
        MqttMessageBuilder messageBuilder = new MqttMessageBuilder();
        if (bo.getClientToken() == null) {
            bo.setClientToken("req_" + System.currentTimeMillis());
        }
        String message = messageBuilder.buildPowerControlMessage(bo.getClientToken(), bo.getPowerSwitch());
        log.info("发送开关控制指令: {}", message);
        return sendRequestToMqtt(message, bo);
    }

    /**
     * 设置设备温度
     */
    @Override
    public Boolean setTemperature(DeviceControlBoPara bo) {
        // 构造控制指令并发送到MQTT
        MqttMessageBuilder messageBuilder = new MqttMessageBuilder();
        if (bo.getClientToken() == null) {
            bo.setClientToken("req_" + System.currentTimeMillis());
        }
        String message = messageBuilder.buildTemperatureControlMessage(bo.getClientToken(), bo.getTemperature());
        log.info("发送温度控制指令: {}", message);
        return sendRequestToMqtt(message, bo);
    }

    /**
     * 设置设备工作模式
     */
    @Override
    public Boolean setGear(DeviceControlBoPara bo) {
        // 构造控制指令并发送到MQTT
        MqttMessageBuilder messageBuilder = new MqttMessageBuilder();
        if (bo.getClientToken() == null) {
            bo.setClientToken("req_" + System.currentTimeMillis());
        }
        String message = messageBuilder.buildGearControlMessage(bo.getClientToken(), bo.getGear());
        log.info("发送档位控制指令: {}", message);
        return sendRequestToMqtt(message, bo);
    }

    /**
     * 设置设备定时器
     */
    @Override
    public Boolean setTimer(DeviceControlBoPara bo) {
        // 构造控制指令并发送到MQTT
        MqttMessageBuilder messageBuilder = new MqttMessageBuilder();
        if (bo.getClientToken() == null) {
            bo.setClientToken("req_" + System.currentTimeMillis());
        }
        String message = messageBuilder.buildTimerControlMessage(bo.getClientToken(), bo.getParams());
        log.info("发送定时器控制指令: {}", message);
        return sendRequestToMqtt(message, bo);
    }

    /**
     * 设置设备其他参数
     *
     * @param bo
     */
    @Override
    public Boolean setOthers(DeviceControlBoPara bo) {
        // 构造控制指令并发送到MQTT
        MqttMessageBuilder messageBuilder = new MqttMessageBuilder();
        if (bo.getClientToken() == null) {
            bo.setClientToken("req_" + System.currentTimeMillis());
        }
        String message = messageBuilder.buildControlMessage("set", bo.getClientToken(), bo.getParams());
        log.info("发送其他参数控制指令: {}", message);
        return sendRequestToMqtt(message, bo);
    }

    /**
     * 查询设备状态
     */
    @Override
    public DeviceControlVo getDeviceStatus(String deviceId) {
        // 构造查询指令并发送到MQTT
        DeviceControl control = buildControlCommand(deviceId, "get", Map.of());
        control.setMessageType("cmd");
        control.setMethod("get");
        // TODO: 实际发送MQTT消息并等待响应
        deviceControlMapper.insert(control);
        // 返回最新状态
        LambdaQueryWrapper<DeviceControl> lqw = Wrappers.lambdaQuery();
        lqw.eq(DeviceControl::getDeviceId, deviceId);
        lqw.eq(DeviceControl::getMessageType, "state");
        lqw.orderByDesc(DeviceControl::getCreateTime);
        List<DeviceControl> controls = deviceControlMapper.selectList(lqw);
        if (!controls.isEmpty()) {
            return MapstructUtils.convert(controls.get(0), DeviceControlVo.class);
        }
        return null;
    }

    /**
     * 构造控制命令对象
     */
    private DeviceControl buildControlCommand(String deviceId, String method, Map<String, Object> params) {
        DeviceControl control = new DeviceControl();
        control.setMethod(method);
        control.setClientToken("req_" + System.currentTimeMillis());
        // TODO: 实际应将params转换为JSON字符串
        control.setParams(params);
        return control;
    }

    /**
     * 发送控制指令到MQTT
     *
     * @param bo 控制参数 params定义的JSON
     * @return 是否发送成功
     */
    private boolean sendRequestToMqtt(String message, DeviceControlBoPara bo) {
        if (!mqttClientService.isConnected()) {
            log.error("MQTT客户端未连接");
            return false;
        }
        try {
            mqttClientService.publish(mqttProperties.getCmdTopic().replace("+", bo.getDeviceId()), message);
        } catch (MqttException e) {
            log.error("MQTT客户端未连接");
            return false;
        }
        return true;
    }
}

